﻿using System;
using System.Collections.Generic;
using System.Windows;

using iStudio.Structure.Engine;
using iStudio.Structure.Wave;

namespace iStudio.Module.PhaseVocoder
{
    public partial class PhaseVocoderWindow
    {
        private SoundTouchWrapper _soundTouch;

        public PhaseVocoderWindow(Structure.Engine.Module module) : base (module)
        {
            InitializeComponent();

            Height = 200;
        }

        private void ButtonApplyClick(object sender, RoutedEventArgs e)
        {
            _soundTouch = new SoundTouchWrapper ();
            _soundTouch.CreateInstance ();


            _soundTouch.SetTempoChange(0);
            _soundTouch.SetPitchSemiTones(0);
            _soundTouch.SetRateChange(0);

            // Apply default SoundTouch settings
            _soundTouch.SetSetting(SoundTouchWrapper.SoundTouchSettings.SettingUseQuickseek, 0);
            _soundTouch.SetTempo ((float) slider_speed.Value);
            _soundTouch.SetPitch ((float) slider_pitch.Value);
            _soundTouch.SetPitchSemiTones ((float) slider_pitch.Value);

            //
            // Go through all selected wave chunks
            //
            
            foreach (WaveTrack track in AudioEngine.Instance.Project.TrackList)
            {
                foreach (WaveChunk chunk in track.TrackChunks)
                {
                    if (chunk.IsSelected)
                    {
                        //
                        // Setup vocoder for each track
                        //

                        _soundTouch.SetChannels (1);
                        _soundTouch.SetSampleRate (track.WaveFormat.SampleRate);

                        //
                        // Create buffer to send in data to SoundTouch
                        //

                        byte[] soundTouchOutBuffer = new byte[8192 * sizeof(float)];

                        ByteAndFloatsConverter convertInputBuffer = new ByteAndFloatsConverter { Floats = chunk.WaveBuffer.ToArray () };
                        ByteAndFloatsConverter convertOutputBuffer = new ByteAndFloatsConverter { Bytes = soundTouchOutBuffer };

                        //
                        // Put in all samples
                        //

                        _soundTouch.PutSamples (convertInputBuffer.Floats, (uint)chunk.WaveBuffer.Count);

                        uint processed = 1;

                        List<float> outBuffer = new List<float>();

                        //
                        // SoundTouch processes samples
                        //
                        
                        while (processed > 0)
                        {
                            processed = _soundTouch.ReceiveSamples(convertOutputBuffer.Floats, 8192);

                            int floatRead = 0;

                            for (int i = 0; i < processed; i++)
                            {
                                outBuffer.Add (BitConverter.ToSingle(convertOutputBuffer.Bytes, floatRead));
                                floatRead += 4;
                            }
                        }

                        //
                        // New samples put back into Wave Buffer
                        //

                        // Temporary solution
                        chunk.WaveBuffer = new WaveCollection<float> (outBuffer);

                        _soundTouch.Clear();

                        //
                        // Logs change into UI
                        //

                        ModuleApi.ConsoleLog("Changed speed and pitch of track: " + track.Name);
                    }
                }
            }

            _soundTouch.Dispose ();
        }
    }
}
